package com.project.petLossSystem.service.impl;

import com.project.petLossSystem.common.Constants;
import com.project.petLossSystem.common.ServiceResultEnum;
import com.project.petLossSystem.mapper.AddressCategoryMapper;
import com.project.petLossSystem.mapper.ImageMatMapper;
import com.project.petLossSystem.mapper.PetCategoryMapper;
import com.project.petLossSystem.mapper.PetPostMapper;
import com.project.petLossSystem.po.AddressCategory;
import com.project.petLossSystem.po.ImageMat;
import com.project.petLossSystem.po.PetPost;
import com.project.petLossSystem.redis.RedisCache;
import com.project.petLossSystem.service.PetPostService;
import com.project.petLossSystem.util.*;
import com.project.petLossSystem.vo.UserVO;
import com.project.petLossSystem.vo.petPost.IndexPetPostVO;
import com.project.petLossSystem.vo.petPost.PetPostDetailVO;
import com.project.petLossSystem.vo.petPost.SearchPetPostVO;
import org.opencv.core.Mat;
import org.opencv.core.Rect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

@Service
public class PetPostServiceImpl implements PetPostService {
    @Autowired
    private PetPostMapper petPostMapper;

    @Autowired
    private PetCategoryMapper petCategoryMapper;

    @Autowired
    private AddressCategoryMapper addressCategoryMapper;

    @Autowired
    private ImageMatMapper imageMatMapper;

    @Autowired
    private RedisCache redisCache;

    @Transactional
    @Override
    public String insertPost(PetPost petPost, String mainImagePath) {
        if (petPostMapper.insertPost(petPost) > 0) {
            // mapper.xml里定义好自动获取id并映射到对象
            ImageMat imageMat = new ImageMat();
            imageMat.setPostId(petPost.getPostId());
            // 生成hist mat
            String mat = ColorHistogramUtil.matToString(ColorHistogramUtil.calculateColorHistogram(mainImagePath, RestTemplateUtil.getRect(Constants.YOLO_URL + mainImagePath)));
            imageMat.setMat(mat);
            if (imageMatMapper.insertMat(imageMat) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            }
        }
        return ServiceResultEnum.DB_ERROR.getResult();
    }

    @Override
    public PageResult getPostPage(PageQueryUtil pageQueryUtil) {
        List<PetPost> posts = petPostMapper.postList(pageQueryUtil);
        long total = petPostMapper.postCount(pageQueryUtil);
        return new PageResult(total, pageQueryUtil.getRows(), pageQueryUtil.getPage(), posts);
    }

    @Override
    public boolean deletePosts(Long[] postIds) {
        return petPostMapper.deletePosts(postIds) > 0;
    }

    @Override
    public List<IndexPetPostVO> getIndexPetPostVO(int number) {
        List<PetPost> posts = petPostMapper.getPostsForViews(number);
        if (!CollectionUtils.isEmpty(posts)) {
            return dealPostList(posts);
        }
        return null;
    }

    public List<IndexPetPostVO> dealPostList(List<PetPost> posts) {
        List<IndexPetPostVO> indexPetPostVOS = MyBeanUtil.copyList(posts, IndexPetPostVO.class);
        for (int i = 0; i < posts.size(); i++) {
            // 设置宠物类型名称
            indexPetPostVOS.get(i).setPetCategoryName(petCategoryMapper.getNameByCategoryId(posts.get(i).getPetCategoryId()));
            // 设置帖子类型名称
            if (posts.get(i).getPostType() == 0) {
                indexPetPostVOS.get(i).setPostTypeName("丢失");
            } else indexPetPostVOS.get(i).setPostTypeName("招领");
            // 设置标题长度
            String title = indexPetPostVOS.get(i).getPostTitle();
            if (title.length() > 10) {
                indexPetPostVOS.get(i).setPostTitle(title.substring(0, 10) + "...");
            }
        }
        return indexPetPostVOS;
    }

    @Override
    public List<SearchPetPostVO> getNewPostsForIndex(int number, byte postType) {
        List<PetPost> posts = petPostMapper.getPostsForTime(number, postType);
        if (CollectionUtils.isEmpty(posts)) {
            return null;
        }
        return dealPostListForSearch(posts);
    }

    public List<SearchPetPostVO> dealPostListForSearch(List<PetPost> posts) {
        List<SearchPetPostVO> searchPetPostVOS = MyBeanUtil.copyList(posts, SearchPetPostVO.class);
        for (int i = 0; i < posts.size(); i++) {
            // 设置宠物类型名称
            searchPetPostVOS.get(i).setPetCategoryName(petCategoryMapper.getNameByCategoryId(posts.get(i).getPetCategoryId()));
            // 设置帖子类型名称
            if (posts.get(i).getPostType() == 0) {
                searchPetPostVOS.get(i).setPostTypeName("丢失");
            } else searchPetPostVOS.get(i).setPostTypeName("招领");
            // 设置标题长度
            String title = searchPetPostVOS.get(i).getPostTitle();
            if (title.length() > 7) {
                searchPetPostVOS.get(i).setPostTitle(title.substring(0, 7) + "...");
            }
            // 设置地址
            searchPetPostVOS.get(i).setAddressCategoryName(addressCategoryMapper.getAddressNameById(posts.get(i).getAddressCategoryId()));
        }
        return searchPetPostVOS;
    }

    @Override
    public PetPostDetailVO getPostDetail(Long postId) {
        PetPost petPost = petPostMapper.getPostById(postId);
        if (ObjectUtils.isEmpty(petPost)) {
            return null;
        }
        PetPostDetailVO petPostDetailVO = new PetPostDetailVO();
        MyBeanUtil.copyProperties(petPost, petPostDetailVO); // copy
        // 设置分类名
        petPostDetailVO.setPetCategoryName(petCategoryMapper.getNameByCategoryId(petPost.getPetCategoryId()));
        // 设置帖子类型名称
        petPostDetailVO.setPostTypeName((petPost.getPostType() == 0) ? "丢失" : "招领");
        // 设置地址名, 三级全部显示
        AddressCategory thirdAddress = addressCategoryMapper.getAddressById(petPost.getAddressCategoryId()); // 三
        AddressCategory secondAddress = addressCategoryMapper.getAddressById(thirdAddress.getParentId()); // 二
        AddressCategory firstAddress = addressCategoryMapper.getAddressById(secondAddress.getParentId()); // 一
        petPostDetailVO.setAddressCategoryName(firstAddress.getAddressName() + " " + secondAddress.getAddressName() + " " + thirdAddress.getAddressName());
        return petPostDetailVO;
    }

    @Override
    public List<IndexPetPostVO> getSelfPosts(HttpSession session) {
        Long userId = ((UserVO) session.getAttribute("user")).getUserId();
        List<PetPost> posts = petPostMapper.getPostsByUserId(userId);
        if (CollectionUtils.isEmpty(posts)) {
            return null;
        }
        return dealPostList(posts);
    }

    @Override
    public PageResult searchPostPage(PageQueryUtil pageQueryUtil) {
        List<PetPost> posts = petPostMapper.postListForSearch(pageQueryUtil);
        long total = petPostMapper.postCountForSearch(pageQueryUtil);
        List<SearchPetPostVO> searchPetPostVOS = new ArrayList<>();
        if (CollectionUtils.isEmpty(posts)) {
            return new PageResult(total, pageQueryUtil.getRows(), pageQueryUtil.getPage(), searchPetPostVOS);
        }
        searchPetPostVOS = dealPostListForSearch(posts); // 处理
        return new PageResult(total, pageQueryUtil.getRows(), pageQueryUtil.getPage(), searchPetPostVOS);
    }

    @Override
    public long getPostCountToday(byte postType) {
        return petPostMapper.getCountTodayByType(postType);
    }

    @Override
    public String getPostIdsForMatch(String imagePath, Long petCategoryId, Byte postType, Integer addressCategoryId, Long userId) {
        // 检测是否有宠物
        Rect rect = RestTemplateUtil.getRect(Constants.YOLO_URL + imagePath);
        if (ObjectUtils.isEmpty(rect)) {
            return ServiceResultEnum.PET_NOT_EXIST.getResult();
        }
        Mat mainHist = ColorHistogramUtil.calculateColorHistogram(imagePath, rect);
        List<String> postIds = new ArrayList<>(); // 存入redis的
        // 获取筛选的帖子，不要自己的
        List<Long> ids = petPostMapper.getPostIdsByCategoryAndTypeAndAddress(petCategoryId, postType, addressCategoryId, userId);
        if (!CollectionUtils.isEmpty(ids)) {
            List<ImageMat> imageMats = imageMatMapper.getMatsByIds(ids); // 不会为空
            // 开始筛选
            for (ImageMat imageMat : imageMats) {
                if (ColorHistogramUtil.compareHist(mainHist, ColorHistogramUtil.stringToMat(imageMat.getMat()))) {
                    postIds.add(String.valueOf(imageMat.getPostId()));
                }
            }
            redisCache.listPutAll(Constants.LIST_KEY_FOR_MATCH + userId, postIds);
        } else {
            redisCache.delete(Constants.LIST_KEY_FOR_MATCH + userId); // 清空缓存
        }
        return ServiceResultEnum.SUCCESS.getResult();
    }

    @Override
    public PageResult matchPostPage(PageQueryUtil pageQueryUtil, List<String> postIds) {
        // postIds不会是空的
        List<PetPost> posts = petPostMapper.postListForMatch(pageQueryUtil, postIds);
        long total = postIds.size();
        List<SearchPetPostVO> searchPetPostVOS = new ArrayList<>();
        searchPetPostVOS = dealPostListForSearch(posts); // 处理
        return new PageResult(total, pageQueryUtil.getRows(), pageQueryUtil.getPage(), searchPetPostVOS);
    }

    @Override
    public String deleteOwnPost(Long postId, HttpSession session) {
        Long userId = ((UserVO) session.getAttribute("user")).getUserId();
        // 查看是否为自己发的帖子
        PetPost petPost = petPostMapper.getPostById(postId);
        if (!ObjectUtils.isEmpty(petPost)) {
            if (petPost.getUserId().equals(userId)) {
                if (petPostMapper.deletePosts(new Long[]{postId}) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            }
        }
        return ServiceResultEnum.POST_NOT_OWNED.getResult();
    }
}
